package zack.gateway.sdk.application;

import com.alibaba.fastjson.JSON;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
import zack.gateway.sdk.GatewayException;
import zack.gateway.sdk.annotations.ApiProducerClazz;
import zack.gateway.sdk.annotations.ApiProducerMethod;
import zack.gateway.sdk.config.GatewaySDKAutoConfig;
import zack.gateway.sdk.config.GatewaySDKProperties;
import zack.gateway.sdk.domain.service.GatewayCenterService;

import java.lang.reflect.Method;

/**
 * @author A1793
 */
public class GatewaySDKApplication implements BeanPostProcessor {
    private GatewaySDKProperties properties;
    private GatewayCenterService service;

    public GatewaySDKApplication(GatewaySDKProperties gatewaySDKProperties, GatewayCenterService gatewayCenterService) {
        this.properties = gatewaySDKProperties;
        this.service = gatewayCenterService;
    }

    /**
     * 在bean对象初始化之后对bean进行操作
     * @param bean
     * @param beanName
     * @return
     * @throws BeansException
     */
    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {

        Logger logger = LoggerFactory.getLogger(GatewaySDKApplication.class);
        //处理接口信息
        ApiProducerClazz apiProducerClazz = bean.getClass().getAnnotation(ApiProducerClazz.class);
        //没有注解说明不是对外提供服务的接口的实现类
        if (apiProducerClazz == null){
            return bean;
        }
        //注册系统应用信息
        logger.info("\n应用注册：系统信息 \nsystemId: {} \nsystemName: {} \nsystemType: {} \nsystemRegistry: {}", properties.getSystemId(), properties.getSystemName(), "RPC", properties.getSystemRegistry());
        service.doRegisterApplication(properties.getAddress(), properties.getSystemId(), properties.getSystemName(), "RPC", properties.getSystemRegistry());
        //处理rpc应用下的接口
        Class<?>[] interfaces = bean.getClass().getInterfaces();
        //一个实现类对应一个对外接口
        if(interfaces.length != 1){
            throw new GatewayException(bean.getClass().getName() + "interfaces not one this is " + JSON.toJSONString(interfaces));

        }
        String interfaceId = interfaces[0].getName();
        logger.info("\n应用注册：接口信息 \nsystemId: {} \ninterfaceId: {} \ninterfaceName: {} \ninterfaceVersion: {}", properties.getSystemId(), interfaceId, apiProducerClazz.interfaceName(), apiProducerClazz.interfaceVersion());
        String interfaceName = apiProducerClazz.interfaceName();
        String interfaceVersion = apiProducerClazz.interfaceVersion();

        service.doRegisterApplicationInterface(properties.getAddress(), properties.getSystemId(), interfaceId, interfaceName, interfaceVersion);
        //处理提供rpc服务的方法
        Method[] methods = bean.getClass().getMethods();
        for(Method method : methods){
            ApiProducerMethod apiProducerMethod = method.getAnnotation(ApiProducerMethod.class);
            if(apiProducerMethod == null){
                continue;
            }
            String methodId = method.getName();
            String methodName = apiProducerMethod.methodName();
            Class<?>[] parameterTypes = method.getParameterTypes();
            StringBuilder parameterTypeBuilder = new StringBuilder();
            for(Class<?> clazz : parameterTypes){
                parameterTypeBuilder.append(clazz.getName()+",");
            }
            String parameterType = parameterTypeBuilder.toString().substring(0,parameterTypeBuilder.toString().lastIndexOf(","));
            logger.info("\n应用注册：方法信息 \nsystemId: {} \ninterfaceId: {} \nmethodId: {} \nmethodName: {} \nparameterType: {} \nuri: {} \nhttpCommandType: {} \nauth: {}",
                    properties.getSystemId(),
                    interfaceId,
                    method.getName(),
                    apiProducerMethod.methodName(),
                    parameterType,
                    apiProducerMethod.uri(),
                    apiProducerMethod.httpCommandType(),
                    apiProducerMethod.auth());
            String uri = apiProducerMethod.uri();
            String httpCommandType = apiProducerMethod.httpCommandType();
            Integer auth = apiProducerMethod.auth();
            service.doRegisterApplicationInterfaceMethod(properties.getAddress(),
                    properties.getSystemId(),
                    interfaceId,
                    methodId,
                    methodName,
                    parameterType,
                    uri,
                    httpCommandType,
                    auth);

        }
      service.doRegisterEvent(properties.getAddress(), properties.getSystemId());
        return bean;
    }
}
